package us.esme.view

/*
 * Copyright 2008 WorldWide Conferencing, LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *    http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by apwant to grabplicable law or agreed to in writing,
 * software distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions
 * and limitations under the License.
 */


import net.liftweb._
import http._
import js._
import JE._
import JsCmds._
import SHtml._
import util._
import Helpers._
import sitemap._
import mapper._
import Loc._

import us.esme._
import model._
import lib._

import scala.xml.{NodeSeq, Text, Elem}

import java.util.logging._

object UserView extends LiftView with MsgFormat {
  val logger: Logger = Logger.getLogger("us.esme.view")
  logger.setLevel(Level.INFO)
  def loggedIn_? = User.loggedIn_?
  
  val ifIsLoggedIn = If(loggedIn_? _, "You must be logged in")

  val menuItems =
  Menu(Loc("userView", List("user_view", "index"), "View User", Hidden)) ::
  Nil

  implicit def fToO(in: () => NodeSeq): Can[() => NodeSeq] = Full(in)
  implicit def fToO2(in: Elem): Can[NodeSeq] = Full(in)

  val dispatch =
  Map("index" -> index _,
      "tag" -> displayTag _,
      "search" -> search _,
      "all" -> allUsers _,
      "conversation" -> conversation _)

  def conversation(): Can[NodeSeq] =   {
    val cid = S.param("cid").map(toLong).openOr(-1L)

    val msgs = Message.findAndPrime(By(Message.conversation, cid),
                                    OrderBy(Message.id, Ascending))

    val replyMap = msgs.foldLeft[Map[Long, List[Message]]](Map.empty){
      case (map, msg) => msg.replyTo.can match {
          case Full(rt) => map + (rt -> (msg :: map.getOrElse(rt, Nil)))
          case _ => map
        }
    }
    
    val start = msgs.firstOption.toList

    def show(what: List[Message]): NodeSeq = {
      what match {
        case Nil => Text("")
        case _ =>
          <ul>
            {
              what.map(m =>
                <li>{formatMsg(m,
                               false, false,
                               Full(() =>
                        show(replyMap.getOrElse(m.id, Nil).reverse)
                      ))}</li>)
            }
          </ul>
      }
    }


	if (User.loggedIn_?) 
	    <lift:surround with="message" at="content">
	      <div>
				<div class="msg-heading">
					<p class="msg-headingtext">Conversation: </p>
					<p class="return-msgs"><lift:Menu.item name="Home">return to messages</lift:Menu.item></p>
				</div>
				  {
		            show(start)
		          }
	      </div>

	    </lift:surround>
	else	
	    <lift:surround with="default" at="content">
	      <div class="msgbox">
				<div class="msg-heading">
					<p class="msg-headingtext">Conversation: </p>
				</div>
				  {
		            show(start)
		          }
	      </div>
	    </lift:surround>

  }

  def index(): Can[NodeSeq] =
  (
	
	if (User.loggedIn_?) 
			<lift:surround with="blank" at="content">
		      {
		        val ui = for (uid <- S.param("uid");
		                      user <- User.findFromWeb(uid)) yield {
		          def updateFollow: JsCmd = SetHtml("following", followOrNot)

		          def followOrNot: NodeSeq = {
		            User.currentUser match {
		              case Full(u) if u != user =>
		                if (u.following_?(user))
		                ajaxButton("Unfollow",  () =>{u.unfollow(user); updateFollow})
		                else ajaxButton("Follow",  () =>{u.follow(user); updateFollow})

		              case _ => <xml:group />
		            }
		          }

				<div class="profile">
					<div class="profile-img">
					{
			     		val r: Can[NodeSeq] =
			     		for (image <- user.image) yield <a href={"/user/"+urlEncode(user.nickname)}><img src={image} alt=""/></a>

			     			r openOr <xml:group>&nbsp;</xml:group>				
					}
					</div> 
					<div class="profile-name">{user.wholeName}</div>
		        	<div class="profile-btn"><span id="following">{followOrNot}</span></div>


				    <ul class="tabNavigation">
					    <li><a href="#messages">Messages</a></li>
					    <li><a href="#followers">Followers</a></li>
					    <li><a href="#following">Following</a></li>
				    </ul>


					<div class="profile-msgs">

						<div class="tabs">

							  <div id="messages">
						        	{
						          		val lst: List[Message] =
						          		Message.findAll(By(Message.author, user), MaxRows(50), OrderBy(Message.id, Descending))
						          		lst.map(m => formatMsg(m, false, true))
						        	}
							  </div>

							  <div id="followers">
		                			<lift:UserSnip.followers userId={user.id.toString}/>
							  </div>

							  <div id="following">
		                			<lift:UserSnip.following userId={user.id.toString}/>
							  </div>

						</div>

					</div>
				</div>


				}
		    	ui openOr (<span>User Not Found</span>)
		 	   }
		   </lift:surround>

	else	
			<lift:surround with="default" at="content">
		      {
		        val ui = for (uid <- S.param("uid");
		                      user <- User.findFromWeb(uid)) yield {
		          def updateFollow: JsCmd = SetHtml("following", followOrNot)

		          def followOrNot: NodeSeq = {
		            User.currentUser match {
		              case Full(u) if u != user =>
		                if (u.following_?(user))
		                ajaxButton("Unfollow",  () =>{u.unfollow(user); updateFollow})
		                else ajaxButton("Follow",  () =>{u.follow(user); updateFollow})

		              case _ => <xml:group />
		            }
		          }

				<div class="profile">
					<div class="profile-img">
					{
			     		val r: Can[NodeSeq] =
			     		for (image <- user.image) yield <a href={"/user/"+urlEncode(user.nickname)}><img src={image} alt=""/></a>

			     			r openOr <xml:group>&nbsp;</xml:group>				
					}
					</div> 
					<div class="profile-name">{user.wholeName}</div>
		        	<div class="profile-btn"><span id="following">{followOrNot}</span></div>


				    <ul class="tabNavigation">
					    <li><a href="#messages">Messages</a></li>
					    <li><a href="#followers">Followers</a></li>
					    <li><a href="#following">Following</a></li>
				    </ul>


					<div class="profile-msgs">

						<div class="tabs">

							  <div id="messages">
						        	{
						          		val lst: List[Message] =
						          		Message.findAll(By(Message.author, user), MaxRows(50), OrderBy(Message.id, Descending))
						          		lst.map(m => formatMsg(m, false, true))
						        	}
							  </div>
					  
							  <div id="followers">
		                			<lift:UserSnip.followers userId={user.id.toString}/>
							  </div>
					  
							  <div id="following">
		                			<lift:UserSnip.following userId={user.id.toString}/>
							  </div>
					
						</div>

					</div>
				</div>


				}
		    	ui openOr (<span>User Not Found</span>)
		 	   }
		   </lift:surround>
   )

 
  def search(): Can[NodeSeq] =
  for (user <- User.currentUser;
       term <- S.param("term")) yield
  <lift:surround with="message" at="content">

    <div>
			<div class="msg-heading">
				<p class="msg-headingtext">Search: {term}</p>
				<p class="return-msgs"><lift:Menu.item name="Home">return to messages</lift:Menu.item></p>
			</div>  

          {
            val lst: List[Message] = Message.search(term, user.following, 50)
            lst.map(m => {formatMsg(m, false, true)})
          }
    </div>

  </lift:surround>
  
  def displayTag(): Can[NodeSeq] =
  
	if (User.loggedIn_?) 
		<lift:surround with="message" at="content">
		      {
		        val ui = for (tagText <- S.param("tag").map(_.trim);
		                      tag <- Tag.find(By(Tag.name, tagText))) yield {
		          val lst = tag.findMessages()

		          (<div>
						<div class="msg-heading">
							<p class="msg-headingtext">Messages tagged with: {tag.name}</p>
							<p class="return-msgs"><lift:Menu.item name="Home">return to messages</lift:Menu.item></p>
						</div>  
		                  {
		                    lst.map(m => {formatMsg(m, false, true)})
		                  }
		           </div>)
		        }
		        ui openOr (<span>Tag Not Found</span>)
		      }
	  </lift:surround>
	else
		<lift:surround with="default" at="content">
		      {
		        val ui = for (tagText <- S.param("tag").map(_.trim);
		                      tag <- Tag.find(By(Tag.name, tagText))) yield {
		          val lst = tag.findMessages()

		          (<div class="msgbox">
						<div class="msg-heading">
							<p class="msg-headingtext">Messages tagged with: {tag.name}</p>
						</div>  
		                  {
		                    lst.map(m => {formatMsg(m, false, true)})
		                  }
		           </div>)
		        }
		        ui openOr (<span>Tag Not Found</span>)
		      }
	  </lift:surround>



	
  
  def allUsers(): Can[NodeSeq] = 

	if (User.loggedIn_?) 
		   <lift:surround with="blank" at="content">
				<div class="profile">
					<div class="contacts-heading">Contacts: </div>

				    <ul class="tabNavigation">
					    <li><a href="#followers">Followers</a></li>
					    <li><a href="#following">Following</a></li>
					    <li><a href="#all">All User</a></li>
				    </ul>
					<div class="profile-msgs">

						<div class="tabs">
							  <div id="followers">
		                			<lift:UserSnip.followers userId={User.id.toString}/>
							  </div>

							  <div id="following">
		                			<lift:UserSnip.following userId={User.id.toString}/>
							  </div>

							  <div id="all">
					        	{
						          User.findAll(OrderBy(User.nickname, Ascending)).map(u => 

							  		<div class="usr">
										<div class="usr-c">
											<div class="usr-image">
											{
									     		val r: Can[NodeSeq] =
									     		for (image <- u.image) yield <a href={"/user/"+urlEncode(u.nickname.is)}><img src={image} alt=""/></a>

									     			r openOr <xml:group>&nbsp;</xml:group>				
											}
											</div>									
											<div class="usr-nickname"><a href={"/user/"+urlEncode(u.nickname.is)}>{u.niceName}</a></div> 
											<div class="usr-name">{u.firstName} {u.lastName}</div>
										</div>
									</div>
							    )
						        }					  
							</div>
						</div>

					</div>
				</div>
		 </lift:surround>

	else	

		   <lift:surround with="default" at="content">
				<div class="profile">
					<div class="contacts-heading">Contacts: </div>

				    <ul class="tabNavigation">
					    <li><a href="#followers">Followers</a></li>
					    <li><a href="#following">Following</a></li>
					    <li><a href="#all">All User</a></li>
				    </ul>
					<div class="profile-msgs">

						<div class="tabs">
							  <div id="followers">
		                			<lift:UserSnip.followers userId={User.id.toString}/>
							  </div>
					  
							  <div id="following">
		                			<lift:UserSnip.following userId={User.id.toString}/>
							  </div>

							  <div id="all">
					        	{
						          User.findAll(OrderBy(User.nickname, Ascending)).map(u => 
					
							  		<div class="usr">
										<div class="usr-c">
											<div class="usr-image">
											{
									     		val r: Can[NodeSeq] =
									     		for (image <- u.image) yield <a href={"/user/"+urlEncode(u.nickname.is)}><img src={image} alt=""/></a>

									     			r openOr <xml:group>&nbsp;</xml:group>				
											}
											</div>									
											<div class="usr-nickname"><a href={"/user/"+urlEncode(u.nickname.is)}>{u.niceName}</a></div> 
											<div class="usr-name">{u.firstName} {u.lastName}</div>
										</div>
									</div>
							    )
						        }					  
							</div>
						</div>

					</div>
				</div>

		 </lift:surround>

}
